﻿using System;
using System.Collections.Generic;
using System.Data.Objects.DataClasses;
using System.Linq;

namespace FranceTriple.Dal
{
    public class PollDal
    {
        public static Int32 CreatePollAndAnswer(Poll entity, List<PollAnswer> answers)
        {
            try
            {
                using (FranceTriple.Dal.Model1Container ctx = new Model1Container())
                {
                    //Décaler à partir de la nouvelle position pour créer une place
                    if (entity.OrderPoll > 0)
                    {
                        foreach (Poll p in ctx.PollSet.Include("ForumTopic").Where(p => p.OrderPoll >= entity.OrderPoll))
                        {
                            if (p.ForumTopic.Id == entity.ForumTopic.Id)
                                p.OrderPoll = p.OrderPoll + 10;
                        }
                    }

                    Poll poll = new Poll();
                    poll.LabelPoll = entity.LabelPoll;
                    poll.DescriptionPoll = entity.DescriptionPoll;
                    poll.DurationInDays = entity.DurationInDays;
                    poll.OrderPoll = entity.OrderPoll;
                    poll.CreationDatePoll = entity.CreationDatePoll;
                    ctx.AddToPollSet(poll);
                    poll.ForumTopic = (from t in ctx.ForumTopicSet where (t.Id == entity.ForumTopic.Id) select t).FirstOrDefault();

                    //Créer les réponses
                    if (answers != null)
                        foreach (PollAnswer answer in answers)
                        {
                            if (answer.LabelPollAnwser != String.Empty)
                                poll.PollAnswer.Add(new PollAnswer()
                                {
                                    LabelPollAnwser = answer.LabelPollAnwser,
                                    NumberVotePollAnswer = answer.NumberVotePollAnswer
                                });
                        }

                    ctx.SaveChanges();
                    return poll.Id;
                }
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("InsertError".ToLocalizedString(), "ForumTopic", ex.Message), ex) { EntityType = typeof(ForumTopic) };
            }
        }

        public static Int32 PollAndCreatePoolUser(int answerID, PollUser entity)
        {
            PollUser polluser = null;

            try
            {
                using (FranceTriple.Dal.Model1Container ctx = new Model1Container())
                {
                    var answer = (from a in ctx.PollAnswerSet
                                  where (a.Id == answerID)
                                  select a).First();

                    answer.NumberVotePollAnswer++;

                    polluser = new PollUser();
                    polluser.UserId = entity.UserId;
                    polluser.UserIp = entity.UserIp;
                    polluser.PollAnswer = answer;
                    ctx.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("RetrieveError".ToLocalizedString(), "PollUser", ex.Message), ex) { EntityType = typeof(PollUser) };
            }
            return polluser.Id;
        }

        public static Boolean CanVote(int pollId, Guid UserId)
        {
            Boolean result = false;
            try
            {
                using (FranceTriple.Dal.Model1Container ctx = new Model1Container())
                {
                    var HasAlreadyVoted = (from p in ctx.PollSet
                                           join aw in ctx.PollAnswerSet
                                           on p.Id equals aw.Poll.Id
                                           join pu in ctx.PollUserSet
                                           on aw.Id equals pu.PollAnswer.Id
                                           where (pu.UserId == UserId
                                           & p.Id == pollId)
                                           select pu).Count() > 0;

                    // Si la durée du sondage est dépassée, le vote est clos.
                    var HasNotExpired = (from p in ctx.PollSet
                                         where p.Id == pollId
                                         & ((p.DurationInDays > 0
                                         & GetExpirationDate(p) > DateTime.Now)
                                         | p.DurationInDays == 0)
                                         select p).Count() > 0;


                    result = !HasAlreadyVoted & HasNotExpired;
                }
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("RetrieveError".ToLocalizedString(), "PollUser", ex.Message), ex) { EntityType = typeof(PollUser) };
            }
            return result;
        }

        // Entity SQL Reference : http://msdn.microsoft.com/en-us/library/bb387118.aspx
        [EdmFunction("Model1", "GetExpirationDate")]
        public static DateTime GetExpirationDate(Poll p)
        {
            throw new NotSupportedException("GetExpirationDate can only be use inside a Linq to Entities query.");
        }

        public static List<Int32> GetPollList(int entityID)
        {
            List<Int32> pollId;

            try
            {
                using (FranceTriple.Dal.Model1Container ctx = new Model1Container())
                {
                    pollId = (from t in ctx.ForumTopicSet
                              from p in t.Poll
                              where (t.Id == entityID)
                              orderby p.OrderPoll
                              select p.Id).ToList();
                }
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("RetrieveError".ToLocalizedString(), "GetPollList", ex.Message), ex) { EntityType = typeof(List<Int32>) };
            }
            return pollId;
        }

        public static Poll GetEntity(Int32 entityID)
        {
            Poll poll;

            try
            {
                using (FranceTriple.Dal.Model1Container ctx = new Model1Container())
                {
                    poll = (from p in ctx.PollSet.Include("PollAnswer")
                            where (p.Id == entityID)
                            select p).FirstOrDefault();
                }
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("RetrieveError".ToLocalizedString(), "Poll", ex.Message), ex) { EntityType = typeof(Poll) };
            }
            return poll;
        }

        public static void UpdateEntity(Poll entity, List<PollAnswer> pollAnswers)
        {
            try
            {
                using (FranceTriple.Dal.Model1Container ctx = new Model1Container())
                {
                    var pollToUpdate = ctx.PollSet.Include("PollAnswer").Where(p => p.Id == entity.Id).FirstOrDefault();
                    if (pollToUpdate == null)
                    {
                        CreatePollAndAnswer(entity, pollAnswers);
                        return;
                    }

                    //if (pollToUpdate.OrderPoll != entity.OrderPoll)
                    //{
                    //    //Utiliser la place libérée par le déplacement
                    //    foreach (Poll p in ctx.PollSet)
                    //    {
                    //        if (p.OrderPoll > pollToUpdate.OrderPoll)
                    //            p.OrderPoll = p.OrderPoll - 10;
                    //    }
                    //    //Décaler à partir de la nouvelle position pour créer une place
                    //    foreach (Poll p in ctx.PollSet)
                    //    {

                    //        if (p.OrderPoll >= entity.OrderPoll)
                    //            p.OrderPoll = p.OrderPoll + 10;
                    //    }
                    //}

                    pollToUpdate.LabelPoll = entity.LabelPoll;
                    pollToUpdate.DescriptionPoll = entity.DescriptionPoll;
                    pollToUpdate.DurationInDays = entity.DurationInDays;

                    //pollToUpdate.OrderPoll = entity.OrderPoll;

                    if (pollAnswers != null)
                    {
                        foreach (PollAnswer answer in pollAnswers)
                        {
                            var pa = pollToUpdate.PollAnswer.ToList().Find(pa1 => pa1.Id == answer.Id);
                            if (pa == null)
                            {
                                if (answer.LabelPollAnwser != String.Empty)
                                    pollToUpdate.PollAnswer.Add(new PollAnswer() { LabelPollAnwser = answer.LabelPollAnwser });
                                continue;
                            }
                            if (answer.LabelPollAnwser == String.Empty)
                            {
                                ctx.PollAnswerSet.DeleteObject(pa);
                                continue;
                            }
                            else
                                pa.LabelPollAnwser = answer.LabelPollAnwser;
                        }
                    }
                    ctx.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("UpdateError".ToLocalizedString(), "PollAnswer", ex.Message), ex) { EntityType = typeof(PollAnswer) };
            }
        }

        public static void DeleteEntity(int entityID)
        {
            try
            {
                using (FranceTriple.Dal.Model1Container ctx = new Model1Container())
                {
                    var pollToUpdate = ctx.PollSet.Where(p => p.Id == entityID).FirstOrDefault();
                    if (pollToUpdate == null)
                        return;

                    //utiliser l'espace libéré dans la numération par le sondage supprimé.
                    foreach (Poll p in ctx.PollSet)
                    {
                        if (p.OrderPoll > pollToUpdate.OrderPoll)
                            p.OrderPoll = p.OrderPoll - 10;
                    }

                    ctx.PollSet.DeleteObject(pollToUpdate);
                    ctx.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("DeleteError".ToLocalizedString(), "Poll", ex.Message), ex) { EntityType = typeof(Poll) };
            }
        }
    }
}
